package com.qingfeng.client.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.qingfeng.client.VO.OrderStoreVo;
import com.qingfeng.client.WxConfig;
import com.qingfeng.client.bean.Buyer;
import com.qingfeng.client.bean.OrderGoods;
import com.qingfeng.client.bean.Trade;
import com.qingfeng.client.dao.OrderGoodsMapper;
import com.qingfeng.client.dao.OrderStoreMapper;
import com.qingfeng.client.dao.TradeMapper;
import com.qingfeng.client.service.PayService;
import com.qingfeng.client.service.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhangyuefei
 * @version 1.0
 * @date 2020/3/6 2:38 下午
 */
@Slf4j
@Api(tags = "微信支付相关接口")
@RestController
@RequestMapping("/wxpay")
public class WxPayApi extends BaseV1Api {


    Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Value("${spring.application.name}")
    private String payName;


    private long expire = 30 * 60 * 1000L;//30分钟

    @Autowired
    private WxPayService wxPayService;

    @Resource
    private TradeMapper tradeDAO;


    @Autowired
    private PayService payService;

    /**
     * 支付结果异步通知
     *
     * @param string
     * @return
     */
    @RequestMapping("/notify")
    public Object mynotify(@RequestBody String string) throws Exception {
        //支付成功之后的回调，可以在这边写支付成功后的逻辑处理
        logger.info("=========================微信付款回调=======================");
        System.out.println(string);
        try {
            Map map = WXPayUtil.xmlToMap(string);
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(map));
            System.out.println(jsonObject);
            if (WXPayUtil.isSignatureValid(map, WxConfig.SECRET)) {
                System.out.println("系统验证签名正确");
                //支付结果
                String result = jsonObject.getString("result_code");
                if (result.equals("SUCCESS")) {
                    //订单号
                    String tradeCode = jsonObject.getString("out_trade_no");
                    //微信订单号
                    String wxTradeCode = jsonObject.getString("transaction_id");
                    String openId = jsonObject.getString("openid");
                    int totalFee = jsonObject.getInteger("total_fee");
                    String endTime = jsonObject.getString("time_end");
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
                    Date date = sdf.parse(endTime);
                    logger.info("=========================微信付款成功=======================");
                    logger.info("订单号tradeCode:"+tradeCode);
                    logger.info("订单号openId:"+openId);
                    logger.info("总价:"+totalFee);
                    payService.paySuccess(tradeCode,totalFee, (int) (date.getTime()/1000),wxTradeCode);
                    logger.info("============================微信付款成功信息结束==============");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        HashMap resMap = new HashMap();
        resMap.put("return_code","SUCCESS");
        resMap.put("return_msg","OK");
        return WXPayUtil.mapToXml(resMap);
    }

    /**
     * 微信内支付统一下单接口
     * @param tradeId
     * @param request
     * @return
     */
    @ApiOperation("申请支付")
    @RequestMapping(value = "/jsApiunifiedorder")
    public Object jsApiUnifiedorder(@RequestParam long tradeId, HttpServletRequest request){
        Buyer buyerBean = getUser();
        Trade tradeBean =tradeDAO.selectById(tradeId);

        //设置订单号
        String code = tradeBean.getCode();

        HashMap<String, String> data = new HashMap<>();
        //必须部分
        data.put("body", payName+"公众号支付，订单编号:"+tradeBean.getCode());//商品的简单描述
        data.put("out_trade_no", code);//订单号，32个字符以内，只能是数字，字母,每笔订单订单号得唯一
//        data.put("detail", detail.toString());//商品详细描述，对于使用单品优惠的商户，改字段必须按照规范上传
        data.put("product_id", tradeBean.getId()+"");//商品id，扫码支付必传。
        data.put("total_fee", tradeBean.getPayment()+"");//订单总金额，单位为分
        data.put("fee_type", "CNY");//币种
        data.put("spbill_create_ip", getRemoteHost(request));//终端ip,
        data.put("notify_url", WxConfig.NOTIFYURL);//异步接收微信支付结果的回调通知
        data.put("trade_type", "JSAPI");//交易类型，JSAPI--公众号支付，NATIVE--原生扫码支付，APP--app支付，MWEB--H5支付
        data.put("sign_type", "MD5");//签名加密方式，默认是MD5
        data.put("openid", buyerBean.getOpenId());//交易类型位公众号支付时必须

        //非必须部分
//        data.put("attach", attach.toString());//会在查询api和支付通知api中返回，可以做为自定义参数使用
        data.put("goods_tag", "");//订单优惠标记
        data.put("limit_pay", "no_credit");//no_credit--限制用户不能使用信用卡支付
        //交易有效时间
        Date now = new Date(tradeBean.getCreateTime() * 1000L);
        Date wil = new Date(now.getTime() + expire);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        data.put("time_start", simpleDateFormat.format(now));//交易起始时间，格式为yyyyMMddHHmmss,或者基于北京时间的时间戳
        data.put("time_expire", simpleDateFormat.format(wil));//交易结束时间，即订单有效时间
//        data.put("scene_info", "{\"store_info\" : {\n" +
//                "\"id\": \"1\",\n" +
//                "\"name\": \"庆丰商城\",\n" +
//                "\"area_code\": \"440305\",\n" +
//                "\"address\": \"南京紫东创意园\" }}\n");//上报实际门店信息
        logger.info("=========================支付下单信息=======================");
        System.out.println(JSON.toJSONString(data));
        logger.info(JSON.toJSONString(data));
        logger.info("=========================支付下单信息结束=====================");
        return wxPayService.unifiedorder(data);
    }



    /**
     * 检查是否付款成功
     * @param tradeId
     * @param request
     * @return
     */
    @RequestMapping(value = "/checkSuccess")
    public Object checkSuccess(@RequestParam long tradeId,HttpServletRequest request) {
        Trade tradeBean = tradeDAO.selectById(tradeId);
        if (tradeBean!=null){
            if (tradeBean.getTradeStat()==2){
                return success();
            }
        }
        return error("付款失败");
    }

    /**
     * 下单
     *
     * @return
     */
    @RequestMapping(value = "/unifiedorder")
    public Object unifiedorder(@RequestParam String tradeType,HttpServletRequest request) {
        HashMap<String, String> data = new HashMap<>();
        //必须部分
        data.put("body", "点盈电商-辣条");//商品的简单描述
        data.put("out_trade_no", "" + System.currentTimeMillis());//订单号，32个字符以内，只能是数字，字母
        data.put("detail", "商品详情");//商品详细描述，对于使用单品优惠的商户，改字段必须按照规范上传
        data.put("product_id", "1234556");//商品id，扫码支付必传。
        data.put("total_fee", "1");//订单总金额，单位为分
        data.put("fee_type", "CNY");//币种
        data.put("spbill_create_ip", getRemoteHost(request));//终端ip,
        data.put("notify_url", WxConfig.NOTIFYURL);//异步接收微信支付结果的回调通知
        data.put("trade_type", tradeType);//交易类型，JSAPI--公众号支付，NATIVE--原生扫码支付，APP--app支付，MWEB--H5支付
        data.put("sign_type", "MD5");//签名加密方式，默认是MD5
        data.put("openid", "oM-okt-dX92QQHXwRouyvJXrN_fY");//交易类型位公众号支付时必须


        //非必须部分
        data.put("attach", "附加数据");//会在查询api和支付通知api中返回，可以做为自定义参数使用
        data.put("goods_tag", "满100减20");//订单优惠标记
        data.put("limit_pay", "no_credit");//no_credit--限制用户不能使用信用卡支付
        //交易有效时间
        Date now = new Date();
        Date wil = new Date(now.getTime() + expire);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        data.put("time_start", simpleDateFormat.format(now));//交易起始时间，格式为yyyyMMddHHmmss,或者基于北京时间的时间戳
        data.put("time_expire", simpleDateFormat.format(wil));//交易结束时间，即订单有效时间
        data.put("scene_info", "{\"store_info\" : {\n" +
                "\"id\": \"1\",\n" +
                "\"name\": \"庆丰商城\",\n" +
                "\"area_code\": \"440305\",\n" +
                "\"address\": \"南京紫东创意园\" }}\n");//上报实际门店信息


        return wxPayService.unifiedorder(data);
    }


    /**
     * 订单查询
     *
     * @param transactionId
     * @return
     */
    @RequestMapping(value = "/orderquery")
    public Object orderQuery(String transactionId) {
        HashMap<String, String> data = new HashMap<>();
        data.put("transaction_id", transactionId);
        try {
            Map<String, String> map = WxConfig.getWxPay().orderQuery(data);
            System.out.println(map);
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(map));
            return jsonObject;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return error();
    }


    @Resource
    private TradeMapper tradeMapper;
//    /**
//     * 退款
//     * @return
//     */
    @RequestMapping(value = "/refund")
    @ResponseBody
    public Object refund(@RequestParam Long tradeId,@RequestParam Long storeId) {
        Trade tradeBean = tradeDAO.selectById(tradeId);

        HashMap<String, String> data = new HashMap<String, String>();
        data.put("transaction_id", tradeBean.getPaycode());//微信交易号
        data.put("out_refund_no", tradeBean.getCode());//商户退款单号
        data.put("total_fee", tradeBean.getPayment() + "");//订单总金额
        data.put("refund_fee", tradeBean.getPayment() + "");//退款金额
        data.put("refund_fee_type", "CNY");//货币
        data.put("refund_desc", "内部测试退款");//退款原因
        try {
            System.out.println(data);
            Map<String, String> map = WxConfig.getWxPay().refund(data);
            System.out.println(map);
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(map));
            System.out.println(jsonObject);
            String result = jsonObject.getString("return_code");
            if (result.equals("SUCCESS")){

            }
            return jsonObject;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return success();
    }

//    /**
//     * 退款查询
//     *
//     * @param transactionId
//     * @return
//     */
//    @RequestMapping(value = "/refundquery")
//    public Object refundQuery(String transactionId) {
//        HashMap<String, String> data = new HashMap<String, String>();
//        data.put("transaction_id", transactionId);
//        try {
//            Map<String, String> map = wxPay.refundQuery(data);
//            System.out.println(map);
//            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(map));
//            return jsonObject;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return APIUtil.genErrorResult();
//    }
//
//
//    /**
//     * 订单支付失败，订单生成之后需要间隔5分钟之后才能关闭
//     * 关闭订单
//     *
//     * @return
//     */
//    @RequestMapping(value = "/closeorder")
//    public Object closeorder(String outTradeNo) {
//        System.out.println("关闭订单");
//        HashMap<String, String> data = new HashMap<String, String>();
//        data.put("out_trade_no", outTradeNo);
//        try {
//            Map<String, String> map = wxPay.closeOrder(data);
//            System.out.println(map);
//            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(map));
//            return jsonObject;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return APIUtil.genErrorResult();
//    }


    private String getRemoteHost(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }

}
